﻿using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using FlanProjectData.Managers;
using FlanProjectData.Helpers;

namespace FlanProject.ScreenMenu
{
	public class InterfaceScreen
	{
		#region Static Properties
		// TODO: remove before delivering
		public static int windowsWidth;
		public static int windowsHeight;

        public static bool isExitingGame = false;
        public static bool savingGame = false;

		#endregion

		#region Properties
		/// <summary>
		/// Logger for tracing data
		/// </summary>
		private static Logger logger = new Logger("InterfaceManager");

		/// <summary>
		/// Contains all components on the screen
		/// </summary>
		protected List<MenuEntry> lstMenuEntrySelectable = new List<MenuEntry>();
		protected List<MenuEntry> lstMenuEntryUnselectable = new List<MenuEntry>();

		/// <summary>
		/// Define the focused Entry
		/// </summary>
		protected int selectedIndex = 0;

		/// <summary>
		/// Determine the number of element can be selectable
		/// </summary>
		protected int countSelectableEntry = 0;

		protected ContentManager Content;

		/// <summary>
		/// Define the background for the windows
		/// </summary>
		protected Texture2D background;

		/// <summary>
		/// Define the percent scale for the background
		/// </summary>
		protected float scalePercent;

		/// <summary>
		/// Source : Sample RolePlayingGameWindows
		/// There are two possible reasons why a screen might be transitioning
		/// off. It could be temporarily going away to make room for another
		/// screen that is on top of it, or it could be going away for good.
		/// This property indicates whether the screen is exiting for real:
		/// if set, the screen will automatically remove itself as soon as the
		/// transition finishes.
		/// </summary>
		public bool IsExiting
		{
			get { return isExiting; }
			protected internal set
			{
				bool fireEvent = !isExiting && value;
				isExiting = value;
				if (fireEvent && (Exiting != null))
				{
					Exiting(this, EventArgs.Empty);
				}
			}
		}

		private bool isExiting = false;

		public bool IsLoadingGame
		{
			get { return isLoadingGame; }
			protected internal set
			{
				bool fireEvent = !isLoadingGame && value;
				isLoadingGame = value;
				if (fireEvent && (LoadingGame != null))
				{
					LoadingGame(this, EventArgs.Empty);
				}
			}
		}

        //the name of the saving files
        public String filesName="";

		private  bool isLoadingGame;

		public event EventHandler Exiting;
		public event EventHandler LoadingGame;

		public bool Visible { get; set; }

		//Children Window
		protected InterfaceScreen imChild = null;

		protected bool GameScreenIsOn = false;

		//Define if the windows is accessible 
		public bool IsFocused { get; set; }

		#endregion

        public InterfaceScreen()
        {

        }

		/// <summary>
		/// Calcul the scale for the background
		/// </summary>
		/// <param name="height">Height of windows'game</param>
		/// <param name="width">Width of windows'game</param>
		public void calcScaleBackground(int height, int width)
		{
			float a = (float)height / (float)this.background.Bounds.Height;
			float b = (float)width / (float)this.background.Bounds.Width; 
			this.scalePercent = Math.Max(a, b);
			logger.Debug("Coef scale for background : " + this.scalePercent);
		}

		public virtual void Initialize()
		{
            windowsHeight = FlanProject.Instance.GraphicsDevice.Viewport.Height;
            windowsWidth = FlanProject.Instance.GraphicsDevice.Viewport.Width;
		}

		#region Load/Unload Content

		public virtual void LoadContent(ContentManager cm)
		{
            logger.Debug("on est dans le loadcontent");
			this.Content = cm;
			// Add the contentmanager refernce to interface's child
			foreach (MenuEntry me in lstMenuEntrySelectable)
			{
                logger.Debug("element selectionable");
				me.LoadContent(this.Content);
			}
			foreach (MenuEntry me in lstMenuEntryUnselectable)
			{
                logger.Debug("element NONselectionable: "+ me.url);
                
				me.LoadContent(this.Content);
			}
		}

		public virtual void UnloadContent()
		{
			this.lstMenuEntryUnselectable = null;
			this.lstMenuEntrySelectable = null;
		}

		#endregion

		#region Virtual methods

		public virtual void HandleInput() 
		{
			if (InputManager.IsActionTriggered(InputManager.Action.Up))
			{
				selectedIndex = (selectedIndex - 1 + lstMenuEntrySelectable.Count) % lstMenuEntrySelectable.Count;
				logger.Debug(selectedIndex.ToString());
			}
			else if (InputManager.IsActionTriggered(InputManager.Action.Down))
			{
				selectedIndex = Math.Abs(selectedIndex + 1) % lstMenuEntrySelectable.Count;
				logger.Debug(selectedIndex.ToString());
			}
			// Validation of selected index
			else if (InputManager.IsActionTriggered(InputManager.Action.Ok))
			{
				this.lstMenuEntrySelectable[this.selectedIndex].OnSelectEntry();
				logger.Info("Validation on :" + selectedIndex.ToString());
			}
		}

		#region Update & Draw Methods

		public virtual void Draw(SpriteBatch sb) 
		{
			try
			{
				if (this.Visible)
				{
					if (!IsExiting)
					{
						if (!GameScreenIsOn)
						{
							if (this.background == null)
							{
								logger.Warn("No Background can be drawed");
							}
							else
							{
								sb.Draw(this.background,
									   new Vector2(0, 0), null, Color.White, 0,
									   new Vector2(0, 0), this.scalePercent, SpriteEffects.None, (float)0.0);
							}
						}

						for (int i = 0; i < lstMenuEntryUnselectable.Count; i++)
						{
							MenuEntry meTmp = lstMenuEntryUnselectable[i];

							meTmp.Draw(sb);
						}

                        for (int i = 0; i < lstMenuEntrySelectable.Count; i++)
                        {
                            MenuEntry meTmp = lstMenuEntrySelectable[i];

                            meTmp.Draw(sb);
                        }
					}
					else
					{
						logger.Info("Encours d'extinction");
					}
				}
				else
				{
					if (imChild != null)
					{
						this.imChild.Draw(sb);
					
                    }
					else
					{
						logger.Warn("No child exist, and no windows can be drawed");
					}
				}
			}
			catch (Exception e)
			{
				logger.Error("Draw() Exception : " + e.Message);
			}
		}

        public virtual void Update(GameTime gameTime)
        {
            if (this.Visible)
            {
                // Updating the keyboard event for the current screen
                this.HandleInput();
                for (int i = 0; i < lstMenuEntrySelectable.Count; i++)
                {
                    if (i == this.selectedIndex)
                    {
                        lstMenuEntrySelectable[i].Select = true;
                    }
                    else if (i != this.selectedIndex && lstMenuEntrySelectable[i].Select)
                    {
                        lstMenuEntrySelectable[i].Select = false;
                    }
                    lstMenuEntrySelectable[i].Update();
                }

                for (int i = 0; i < lstMenuEntryUnselectable.Count; i++)
                {
                    lstMenuEntryUnselectable[i].Update();
                }
            }
            else if (!this.Visible && this.imChild != null)
            {
                this.imChild.Update();

                if (this.imChild.Visible && this.imChild.IsExiting)
                {
                    this.imChild.Visible = false;
                    this.Visible = true;
                    this.imChild.UnloadContent();
                    this.imChild = null;
                }
                else if (this.imChild.IsLoadingGame)
                {
                    this.IsLoadingGame = true;
                    this.filesName = this.imChild.filesName;
                }
            }
        }

		public virtual void Update()
		{
			if (this.Visible)
			{
				// Updating the keyboard event for the current screen
				this.HandleInput();
				for (int i = 0; i < lstMenuEntrySelectable.Count; i++)
				{
					if (i == this.selectedIndex)
					{
						lstMenuEntrySelectable[i].Select = true;
					}
					else if (i != this.selectedIndex && lstMenuEntrySelectable[i].Select)
					{
						lstMenuEntrySelectable[i].Select = false;
					}
					lstMenuEntrySelectable[i].Update();
				}

				for (int i = 0; i < lstMenuEntryUnselectable.Count; i++)
				{
					lstMenuEntryUnselectable[i].Update();
				}
			}
			else if (!this.Visible && this.imChild != null)
			{
				this.imChild.Update();

				if (this.imChild.Visible && this.imChild.IsExiting)
				{
					this.imChild.Visible = false;
					this.Visible = true;
					this.imChild.UnloadContent();
					this.imChild = null;
				}
                else if (this.imChild.IsLoadingGame)
                { 
                    this.IsLoadingGame = true;
                    this.filesName = this.imChild.filesName;
                }
			}
		}

		public virtual void OnSelectEntry() 
		{ 
		}

		#endregion


		#endregion

		#region Methods

		public void ExitScreen()
		{
			logger.Info("The screen is shuting down");
			this.IsExiting = true;
		}
        public void ExitGame()
        {
            logger.Info("The game is shuting down");
            isExitingGame = true;
        }

		public void ExitScreen(object sender, EventArgs e)
		{
			ExitScreen();
		}

        public void ExitGame(object sender, EventArgs e)
        {
            this.ExitScreen();
            this.ExitGame();
        }
        public void saveGame(object sender, EventArgs e)
        {
            savingGame = true;
            this.ExitScreen();
        }

		#endregion



		#region Virtual Enum

		protected enum AccessibleForm
		{
		}

		#endregion
	
	}
}
